using System;
using System.Collections.Generic;
using System.Text;

using System.Xml;

using NUnit.Framework;


using OWED.Network.Messages;
using OWED.Network.Messages.General;
using OWED.Network.Messages.Reply;

using OWED.Network;

using System.Threading;

namespace OWED.Network
{
	[TestFixture]
	public class TestServer
	{
		class ExampleServer : Server
		{
			public ExampleServer(int port) : base(port) {

			}
			protected override void ConnectionLoop(object me)
			{
				IProtocolItem l = Wait(me);
				Console.WriteLine("Got:{0}", l);
				if ((l as Login) == null) {
					Console.WriteLine("Login type failure:");
					Console.WriteLine(l);
					Reply(me, new PassFail(false,
						new Reason(1, "YOu have to login first!")));
				} else
					Reply(me, new PassFail(true,
						new Reason(0, "Correct!")));
				Random r = new Random();
				int n = 0;
				while (true) {
					IProtocolItem msg = Wait(me);
					Console.WriteLine("Got:{0}", msg);
					Console.WriteLine("Processing...{0}", n);
					Thread.Sleep(r.Next(20, 250));
					Console.WriteLine("Done!");
					GetComment get = msg as GetComment;
					if (get.DiscussionID.id != n)
						Reply(me, new PassFail(false,
							new Reason(2, "Out of order!")));
					else
						Reply(me, new PassFail(true,
							new Reason(0, "Cause I likes ya")));
					++n;
				}
			}
		}

        [Test]
        public void TestMultipleConnection()
        {
            ExampleServer s = new ExampleServer(666);
            Connection c = new Connection("localhost", 666);

            bool pass = true;
            String error = null;

            EventWaitHandle wait = new EventWaitHandle(false,
                EventResetMode.AutoReset);

            Console.WriteLine("This test code occasionally fails in itself");
            Console.WriteLine("It fails by never finishing.");

            OWEDReply response = delegate(XmlDocument document)
            {
                PassFail reply = MessageGet.GetFromXml(document) as PassFail;
                if (!(reply.pass))
                {
                    error = "Something with login being wrong?";
                    pass = false;
                }
                wait.Set();
            };

            c.Send(new Login(new User("chris"), new Password("pass")).ToXml(), response);
            for (int i = 0; i < 32; ++i)
            {
                c.Send(new GetComment(new User("Chris"),
                                    new DiscussionID(i),
                                    new CommentRef(23)).ToXml(), response);
            }
            wait.WaitOne();
            for (int i = 0; i < 32; ++i)
            {
                wait.WaitOne();
            }


            c.Dispose();
            s.Dispose();
            Assert.IsTrue(pass, error);
        }
	}
}
